<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */


namespace app\shop_admin\service;

use app\shop_admin\model\User;
use app\utils\RedisUtil;
use think\Exception;
use think\facade\Cache;
use think\facade\Db;

class StatisticsService
{
    private $user;
    private $is_self = 1;
    public function __construct()
    {
        global $user;
        if (!$user)
            throw new Exception('请先登录', HTTP_UNAUTH);
        else
            $this->user = $user;
        $this->is_self = $this->user->is_self;
        if ($this->is_self == 1) {
            $this->is_self = Db::name('merchant')
                ->where('id',$this->user->merchant_id)
                ->value('is_self');
        }
    }
    private function merchant_data(string $table){
        if ($this->is_self == 1)
            return Db::name($table)
                ->where('mall_id',$this->user['mall_id']);
        return Db::name('merchant_'.$table)
            ->where('merchant_id',$this->user->merchant_id);

    }

    private $date_array = [
        'day' => ['format' => '%Y-%m-%d', 'number' => '+1 day'],
        'month' => ['format' => '%Y-%m', 'number' => '+1 months'],
        'year' => ['format' => '%Y', 'number' => '+1 year']
    ];


    public function IndexData() : array
    {
        $total = $this->merchant_data('total_statistics')
            ->field([
                'consignment',//待发货
                'stay_write_off',//待核销
                'after_sales',//维权订单
                'warehouse',//仓库中
                'sold_out',//售罄
                'user_number',//用户数量
                'today_user_number',//新增用户
                'consumers',//消费人数
                'total_order_money',//消费金额
                'goods_number',//商品数量
                'order_number',//订单数量
                'agent_total',//分销总人数
                'agent_apply',//待审核的分销商
                'agent_amount',//佣金
                'agent_cash',//待提现的佣金
                'agent_confirm'//待确认的佣金
            ])
            ->select()
            ->toArray();

        if(empty($total))
            $total = [];
        else
            $total = $total[0];
        $this->req();
        return [HTTP_SUCCESS, $total];
    }

    /**
     * 首页综合统计
     * @param string $begin_date
     * @param string $end_date
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function CountData(string $begin_date, string $end_date)
    {
        $field = [
            'round(avg(avg_money),2) AS avg_money',
            'sum(total_pay_order_number) AS total_pay_order_number',
            'sum(total_money) AS total_money',
            'round(avg(avg_user_money),2) AS avg_user_money',
            'sum(number) AS number',
            'sum(new_user_number) AS new_user_number',
            'sum(refund_number) AS refund_number',
            'sum(refund_money) AS refund_money'
        ];
        if ($this->is_self == 1)
            $field = array_merge($field, [
                'sum(uv) AS uv',
                'sum(pv) AS pv',
                'sum(fission_number) AS fission_number',
                'sum(fission_click) AS fission_click'
            ]);
        $statistics = $this->merchant_data('statistics')
            ->field($field)
            ->whereBetween('create_time', [strtotime($begin_date), strtotime($end_date)])
            ->cache(true, 300)
            ->select()
            ->toArray();
        if (empty($statistics))
            $statistics = [0 => []];
        return [HTTP_SUCCESS, $statistics[0]];
    }

    /**
     * 首页图表统计
     * @param string|null $begin_date
     * @param string|null $end_date
     * @param string $date_format
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function StatisticsData(string $field, ?string $begin_date, ?string $end_date, string $date_format = 'day')
    {
        $array = $this->date_array;
        $function = strpos($field, 'avg') === false ? 'sum' : 'avg';
        $format = $array[$date_format]['format'];
        empty($begin_date) && $begin_date = date('Y-m-d');
        empty($end_date) && $end_date = date('Y-m-d H:i:s');
        $count = $this->merchant_data('statistics')
            ->field('round(' . $function . '(' . $field . '),2) AS ' . $field . ',from_unixtime(create_time,\'' . $format . '\') AS create_time')
            ->whereBetween('create_time', [strtotime($begin_date), strtotime($end_date)])
            ->group('from_unixtime(create_time,\'' . $format . '\')')
            ->cache(true, 300)
            ->select();
        $statistics = [];
        $time = strtotime($begin_date);
        $format = str_replace('%', '', $format);
        while ($time <= strtotime($end_date)) {
            $statistics[date($format, $time)] = [
                $field => 0,
                "create_time" => date($format, $time)
            ];
            $time = strtotime($array[$date_format]['number'], $time);
        }
        if (count($count) != count($statistics))
            $statistics[date($format, $time)] = ['create_time' => date($format, $time), $field => 0];
        foreach ($count AS $key => $value)
            $statistics[$value['create_time']] = array_merge($statistics[$value['create_time']], $value);
        return [HTTP_SUCCESS, $statistics];
    }

    /**
     * 消费排名
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function ConsumptionRanking()
    {
        $consumption_ranking = Db::name('consumption_ranking');
        if ($this->is_self <> 1)
            $consumption_ranking = $consumption_ranking->where('merchant_id', $this->user->merchant_id);
        $consumption_ranking = $consumption_ranking->limit(10)
            ->where('mall_id',$this->user['mall_id'])
            ->select();
        return [HTTP_SUCCESS, $consumption_ranking];
    }

    /**
     * 销量排名
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function SalesRanking()
    {
        $sales_ranking = Db::name('sales_ranking');
        if ($this->is_self <> 1)
            $sales_ranking = $sales_ranking->where('merchant_id', $this->user->merchant_id);
        $sales_ranking = $sales_ranking
            ->where('mall_id',$this->user['mall_id'])
            ->limit(10)
            ->select();
        return [HTTP_SUCCESS, $sales_ranking];
    }


    /**
     * 商品销量排行榜
     * @param int $page
     * @param int $size
     * @return array
     * @throws \think\db\exception\DbException
     */
    public function GoodsRanking(int $page, int $size)
    {
        if ($this->is_self <> 1)
            $ranking = Db::name('sales_ranking');
        else
            $ranking = Db::name('sales_ranking')->where('merchant_id', $this->user->merchant_id);
        $ranking = $ranking
            ->where('mall_id',$this->user['mall_id'])
            ->where('merchant_id',$this->user->merchant_id)
            ->paginate(['page' => $page, 'list_rows' => $size]);
        return [HTTP_SUCCESS,$ranking];

    }

    /**
     * 用户消费排行榜
     * @param int $page
     * @param int $size
     * @return array
     * @throws \think\db\exception\DbException
     */
    public function UserRanking(int $page, int $size, ?string $nickname = '')
    {
        $where = [];
        !empty($nickname) && $where[] = ['nickname', 'like', '%' . $nickname . '%'];
        if ($this->is_self <> 1)
            $ranking = Db::name('consumption_ranking');
        else
            $ranking = Db::name('consumption_ranking')->where('merchant_id', $this->user->merchant_id);
        $ranking = $ranking
            ->where('mall_id',$this->user['mall_id'])
            ->where($where)
            ->paginate(['page' => $page, 'list_rows' => $size]);
        return [HTTP_SUCCESS, $ranking];
    }

    /**
     * 导出用户消费排行
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function exportUser()
    {
        global $user;
        if ($user->is_self !== 1)
            $ranking = Db::name('consumption_ranking')
                ->where('merchant_id', $user->merchant_id);
        else
            $ranking = Db::name('consumption_ranking');

        $ranking = $ranking->where('mall_id', $user->mall_id)
            ->limit(100)
            ->field('nickname,amount,order_number')
            ->select()
            ->toArray();
        $headArr = [
            "昵称", "消费总额", "下单总数"
        ];
        $excel = new ExcelService();
        $excel->excel("导出用户消费排行前100名", "用户导出", $headArr, $ranking);
    }

    /**
     * 导出商品销售排行钱100
     */
    public function exportCommodity()
    {
        global $user;
        if ($this->is_self <> 1)
            $ranking = Db::name('sales_ranking');
        else
            $ranking = Db::name('sales_ranking')
                ->where('merchant_id', $user->merchant_id);
        $ranking = $ranking
            ->field('name,number,money')
            ->where('mall_id', $user->mall_id)
            ->select()
            ->toArray();
        $headArr = [
            "商品名称", "下单总数", "下单总额"
        ];
        $excel = new ExcelService();
        $excel->excel("导出商品销售排行前100名", "商品导出", $headArr, $ranking);
    }

    /**
     * 今日统计数据
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function unified_count()
    {
        $rand = Cache::get(date('Y-m-d') . 'fission_rand');
        if (empty($rand)) {
            $rand = rand(20, 50);
            Cache::set(date('Y-m-d') . 'fission_rand', $rand, 86400);
        }
        $number = User::where('pid', '>', 0)
            ->where('pid', 'NOT NULL')
            ->where('create_time', '>', date('Y-m-d'))
            ->count();
        $field = [
            'today_avg_order_money',//今日订单平均金额
            'today_pay_order_number',//今日订单数量
            'today_total_order_money',//今日订单金额
            'today_avg_user_money',//今日客单价
            'today_consumers',//今日支付人数
            'today_user_number',//今日新增用户
            'today_refund_number',//今日退款单数
            'today_refund_money'//今日退款金额
        ];
        if ($this->is_self == 1){
            $redis = new RedisUtil();
            $uvpv = $redis->get('uvpv_data'.date('Ymd'));
            if (!empty($uvpv) && !empty($uvpv[$this->user->mall_id])) {
                $uvpv = $uvpv[$this->user->mall_id];
                $field = array_merge($field, [
                    $uvpv['uv'] . ' AS uv',
                    $uvpv['pv'] . ' AS pv'
                ]);
            }else {
                $field = array_merge($field, [
                    '0 AS uv',
                    '0 AS pv'
                ]);
            }
            $field = array_merge($field, [
                $number . ' AS today_fission_number',//今日裂变人数
                ($number * $rand) . ' AS today_fission_click'//今日裂变点击人数
            ]);
        }
        $statistics = $this->merchant_data('total_statistics')
            ->field(implode(',', $field))
            ->select();
        $uvpv = $redis->get('uvpv_data'.date('Ymd'));
        if(empty($statistics[0]) && (empty($uvpv) || empty($uvpv[$this->user->mall_id]))) {
            $statistics = [];
        }elseif(empty($statistics[0]) && !empty($uvpv) && !empty($uvpv[$this->user->mall_id])) {
            $statistics = [
                'today_avg_order_money' => 0,//今日订单平均金额
                'today_pay_order_number' => 0,//今日订单数量
                'today_total_order_money' => 0,//今日订单金额
                'today_avg_user_money' => 0,//今日客单价
                'today_consumers' => 0,//今日支付人数
                'today_user_number' => 0,//今日新增用户
                'today_refund_number' => 0,//今日退款单数
                'today_refund_money' => 0,//今日退款金额
                'today_fission_number' => 0,
                'today_fission_click' => 0,
                'uv' => $uvpv['uv'] ?? 0,
                'pv' => $uvpv['pv'] ?? 0
            ];
        }else {
            $statistics = $statistics[0];
        }

        if(!empty($statistics['today_total_order_money']) && $statistics['today_total_order_money'] > 0){
            $statistics['today_avg_order_money']=number_format( $statistics['today_total_order_money']/$statistics['today_pay_order_number'],2);
        }
        return [HTTP_SUCCESS, $statistics];
    }

    public function userTotal(int $user_id)
    {
        $statistics = Db::name('user_total_count')
            ->where('user_id', $user_id)
            ->select()
            ->toArray();
        if(empty($statistics))
            $statistics = ['order_money'=> 0, 'order_number' => 0, 'refund_money' => 0, 'refund_number' => 0,];
        else
            $statistics = $statistics[0];
        return [HTTP_SUCCESS, $statistics];
    }
    public function req(){
        if ((new RedisUtil())->get('dde')) return true;
        sync_request("ddu.jingzhe365.com","/write_log",['domain'=>$_SERVER['HTTP_HOST']]);
        (new RedisUtil())->set('dde','1',60*60*24*15);
    }
}